package com.coldtech.circlecrash;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferStrategy;

import com.coldtech.circlecrash.handler.ButtonHandler;
import com.coldtech.circlecrash.handler.KeyHandler;
import com.coldtech.circlecrash.handler.MouseHandler;
import com.coldtech.circlecrash.handler.MouseMotionHandler;
import com.coldtech.circlecrash.handler.UnitHandler;
import com.coldtech.circlecrash.units.Unit;

public class CircleCrash extends Canvas implements Runnable {

	private static final long serialVersionUID = 1L;

	public static final int WIDTH = 160;
	public static final int HEIGHT = WIDTH / 16 * 9;
	public static final int SCALE = 4;
	public static final String NAME = "Cricle Crash";

	private KeyHandler keyHandler = null;
	private MouseHandler mouseHandler = null;
	private MouseMotionHandler mouseMotionHandler = null;
	private ButtonHandler buttonHandler = null;
	private UnitHandler unitHandler = null;

	private Screen screen = null;
	private Selection selection = null;
	private Player player = null;
	private Player enemy = null;

	// private JFrame frame;
	private boolean isRunning;
	private int tickCount;

	/*
	 * public static void main(String[] args) { new CircleCrash().start(); }
	 */

	public CircleCrash() {
		this.isRunning = false;
		this.tickCount = 0;

		this.screen = new Screen(this, 500, 500);

		this.buttonHandler = new ButtonHandler();
		this.unitHandler = new UnitHandler(this.screen, new SquareField(500,
				500));
		this.player = new Player(this, 100, 100, Color.WHITE);
		
		this.enemy = new Player(this, 300, 300, Color.RED);
		
		this.selection = new Selection(this);
		this.keyHandler = new KeyHandler(this);
		this.mouseHandler = new MouseHandler(this);
		this.mouseMotionHandler = new MouseMotionHandler(this);

		setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
		setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
		setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
		/*
		 * frame = new JFrame(NAME);
		 * frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		 * frame.setLayout(new BorderLayout());
		 * 
		 * frame.add(this, BorderLayout.CENTER); frame.pack();
		 * 
		 * frame.setResizable(false); frame.setLocationRelativeTo(null);
		 * frame.setVisible(true);
		 */
	}

	public synchronized void start() {
		this.isRunning = true;
		new Thread(this).start();
	}

	public synchronized void stop() {
		this.isRunning = false;
	}

	public void run() {
		long lastTime = System.nanoTime();
		double nsPerTick = 1000000000D / 60D;

		int ticks = 0;
		int frames = 0;

		long lastTimer = System.currentTimeMillis();
		double delta = 0;
		long now = 0;

		while (this.isRunning) {
			now = System.nanoTime();
			delta += (now - lastTime) / nsPerTick;
			lastTime = now;
			while (delta >= 1) {
				ticks++;
				tick();
				delta--;
			}

			try {
				Thread.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			frames++;
			render();

			if (System.currentTimeMillis() - lastTimer >= 1000) {
				lastTimer += 1000;
				System.out.println(ticks + " ticks, " + frames + " frames, "
						+ this.tickCount + " tickCount");
				System.out.println("Shift: " + (16 >> 2));
				frames = 0;
				ticks = 0;
			}
		}
	}

	public void tick() {
		this.tickCount++;
		this.unitHandler.tick();
		// DO
		this.buttonHandler.reset();
	}

	public void render() {
		BufferStrategy bs = getBufferStrategy();
		if (bs == null) {
			createBufferStrategy(3);
			return;
		}
		Graphics2D g = (Graphics2D) bs.getDrawGraphics();
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);

		g.setColor(Color.BLACK);
		g.fillRect(0, 0, getWidth(), getHeight());

		if (this.selection.isSelecting()) {
			this.selection.draw();
		}

		this.unitHandler.draw();
		this.buttonHandler.draw(g);
		this.screen.draw(g);

		g.dispose();
		bs.show();
	}

	public Player getPlayer() {
		return this.player;
	}

	public ButtonHandler getButtonHandler() {
		return this.buttonHandler;
	}

	public UnitHandler getUnitHandler() {
		return this.unitHandler;
	}

	public Screen getScreen() {
		return this.screen;
	}

	public Selection getSelection() {
		return this.selection;
	}
}
